/*
 * Bucket.cpp
 *
 *  Created on: 11/10/2011
 *      Author: gisedaye
 */

#include "Bucket.h"

Bucket::Bucket(int bucketNumber) {
	this->bucketNumber=bucketNumber;
}

void Bucket::insertRecord(Record * record,bool * overflow){
	if(this->recordExists(record->getId())){
		throw ExceptionExists();
	}
	int pos= this->getPosition(record->getId());
	vector<Record*>::iterator it = this->records.begin();
	this->records.insert(it+pos,record);
	if(this->isOverflow())
		*overflow=true;

}

void Bucket::modifyRecord(Record * record, bool * overflow){
	if(!this->recordExists(record->getId())){
		throw ExceptionNotFound();
	}
	int pos= this->getPosition(record->getId());
	this->records[pos]->setValue(record->getValue());
	if(this->isOverflow())
		*overflow=true;
}

void Bucket::deleteRecord(Record * record, bool * underflow){
	if(!this->recordExists(record->getId())){
		throw ExceptionNotFound();
	}
	int pos= this->getPosition(record->getId());
	delete this->records[pos];

	vector<Record*>::iterator it = this->records.begin();
	this->records.erase(it+pos);
	if(this->isUnderflow())
		*underflow=true;
}


bool Bucket::recordExists(string id){
	unsigned int i=0;
	bool exists=false;
	while((i<this->records.size())&&(!exists)){
		if(this->records[i]->getId()==id)
			exists=true;
		i++;
	}
	return exists;
}
void Bucket::writeToFile(string filename){
	 string bucketString="";
	 bucketString+=Utils::intToString(this->getBucketSize());
	 bucketString+='|';
	 bucketString+=Utils::intToString(this->bucketNumber);
	 bucketString+='|';
	 bucketString+=this->getRecordsAsString();
	 FileWritable::writeToFile(filename,bucketString);

}
void Bucket::loadBucket(string filename,int bucketNumber){
	string bucketString=FileLoader::getBucketFromFile(filename, bucketNumber);
	this->loadStringToClass(bucketString);

}
string Bucket::getRecordsAsString(){
	string recordsString="";
	recordsString=Utils::intToString(this->records.size())+"|";
	for(unsigned int i=0;i<this->records.size();i++){
		recordsString+=this->records[i]->toString();
		if(i!=this->records.size()-1){
			recordsString+=';';
		}
	}
	return recordsString;
}

void Bucket::loadStringToClass(string bucketString){
	cout<<"BUCKETSTRING"<<bucketString<<endl;
	int bucketSize=Utils::stringToInt(bucketString.substr(0,sizeof(int)));
	cout<<"BUCKETSIZE"<<bucketSize<<endl;
	bucketString=bucketString.substr(sizeof(int), bucketString.length()-sizeof(int));
	cout<<"BUCKETSTRING"<<bucketString<<endl;
	this->bucketNumber=Utils::stringToInt(bucketString.substr(0,sizeof(int)));
	cout<<"Bucket numb: "<<this->bucketNumber<<endl;
	bucketString=bucketString.substr(bucketString.find_first_of('|')+1,bucketString.length()-bucketString.find_first_of('|'));
	string recordsString=bucketString;
	cout<<"RecordSTRING"<<recordsString<<endl;
	this->loadRecordsToClass(recordsString);
}
void Bucket::loadRecordsToClass(string recordsString){
	int recordsSize=Utils::stringToInt(recordsString.substr(0,sizeof(int)));
	cout<<"RECORDSIZE "<<recordsSize<<endl;
	recordsString=recordsString.substr(recordsString.find_first_of('|')+1,(recordsString.length()-(recordsString.find_first_of('|')+1)));
	cout<<"RECORDSTRING "<<recordsString<<endl;
	int i=0;
	string record="";
	string id;
	string value;
	while(i<recordsSize){
		id="";
		value="";
		if(recordsSize>1){
			record=recordsString.substr(0,recordsString.find_first_of(';'));
			id=record.substr(0,record.find_first_of('-'));
			value=record.substr(record.find_first_of('-')+1,record.length()-(record.find_first_of('-')+1));
			this->records.push_back(new Record(id, value));
			if(i!=recordsSize-1)
				recordsString=recordsString.substr(recordsString.find_first_of(';')+1,recordsString.length()-(recordsString.find_first_of(';')+1));
		}else{
			record=recordsString;
			id=record.substr(0,record.find_first_of('-'));
			cout<<"ID "<<id<<endl;
			value=record.substr(record.find_first_of('-')+1,record.length()-(record.find_first_of('-')+1));
			cout<<"VALUE "<<value<<endl;
			this->records.push_back(new Record(id, value));
		}
		i++;
	}

}

int Bucket::getBucketSize(){
	return BUCKET_SIZE;
}

int Bucket::getBucketNumber(){
	return this->bucketNumber;
}

void Bucket::setBucketNumber(int bucketNumb){
	this->bucketNumber=bucketNumb;
}

int Bucket::getPosition(string id){
	unsigned int i=0;
	bool exists=false;
	while((i<this->records.size())&&(Utils::stringToInt(this->records[i]->getId())<Utils::stringToInt(id))&&(!exists)){
		if(this->records[i]->getId()==id)
			exists=true;
		i++;
	}
	return i;
}
bool Bucket::isUnderflow(){
	return this->records.size()==0;
}
bool Bucket::isOverflow(){
	return this->records.size()>this->getBucketSize();
}

int Bucket::getDispersionNumber()
{
	return dispersionNumber;
}

vector<Record*> Bucket::getRecords()
{
	return records;
}

void Bucket::setDispersionNumber(int dispersionNumber)
{
	this->dispersionNumber = dispersionNumber;
}

void Bucket::setRecords(vector<Record*> records)
{
	this->records = records;
}

Bucket::~Bucket() {
	// TODO Auto-generated destructor stub
}
